﻿/*----------------------------------------------------------------
//   Copyright (C) 2010 YMSOFT All rights reserved 
//
//   CLR版本:   2.0.50727.3620
//   Namespace: ART.Common
//   FileName : JGridView
//   Description: 
// 
//   Created by YAOMING at 2012-2-22 11:31:52
//   http://www.loverer.com QQ:78867011
//
//   Modified: 
//   Modify description: 
//
//----------------------------------------------------------------*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web;
using System.Web.UI;
using System.Data;
using System.Collections;

namespace ART.Common
{
    /// <summary>
    /// 动态生成复合表头及导出Excel帮助类
    /// 相邻父列头之间用'#'分隔,父列头与子列头用空格(' ')分隔,相邻子列头用逗号分隔(',').
    ///  两行：序号#分公司#组别#本日成功签约单数 预警,续约,流失,合计#累计成功签约单数 预警,续约,流失,合计#任务数#完成比例#排名
    ///  三行：等级#级别#上期结存 件数, 重量,比例#本期调入 收购调入 件数,重量,比例#本期发出 车间投料 件数,重量,比例#本期发出 产品外销百分比 件数,重量,比例#平均值
    //  三行时请注意：列头要重复
    /// </summary>
    public class JGridView
    {
        /// <summary>
        /// GridView分组
        /// </summary>
        public class GridViewGroup
        {
            /// <summary>
            /// 向DataTable中添加 行分组汇总列
            /// </summary>
            /// <param name="olDtable">DataTable</param>
            /// <param name="bjName">分组列</param>
            /// <param name="numColumsStr">需要计算求和的列，用#分割</param>
            /// <returns></returns>
            public static DataTable AddGurop(DataTable olDtable, string bjName, string numColumsStr)
            {

                //为null 或 只有一条记录对于分组来说无意义
                if (olDtable == null)
                {
                    return olDtable;
                }
                DataTable table = TableSort(olDtable, bjName);
                Dictionary<int, DataRow> rows = new Dictionary<int, DataRow>();//存放汇总行

                IList<string> numColumns = new List<string>();
                if (numColumsStr == null)
                {
                    numColumns = GetNumColumns(table);
                }
                else
                {
                    string[] columns = numColumsStr.Split('#');
                    foreach (string str in columns)
                    {
                        numColumns.Add(str);
                    }
                }

                string prevDept = table.Rows[0][bjName].ToString();//
                int NoOwn = 0;//同组项的第一行记录的位置
                int index = -1;//索引
                foreach (DataRow item in table.Rows)
                {
                    index++;//当前行索引 
                    //如果相邻两行 分组标记相同 则继续寻找下行，否则该行为同组的最后一行。进行数据处理
                    //item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行
                    if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1)
                    {
                        continue;
                    }
                    else if (index == table.Rows.Count - 1)
                    {
                        if (item[bjName].ToString() != prevDept)
                        {
                            DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                            rows.Add(index + rows.Count, row);

                            DataRow row2 = table.NewRow();
                            foreach (string columnName in numColumns)
                            {
                                row2[columnName] = item[columnName];
                            }
                            rows.Add(index + rows.Count + 1, row2);
                        }
                        else
                        {
                            DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                            rows.Add(index + rows.Count + 1, row);
                        }

                    }
                    else
                    {
                        prevDept = item[bjName].ToString();//当前分组标记
                        DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                        NoOwn = index;
                        rows.Add(index + rows.Count, row);
                    }
                }

                DataRow sumRow = CreateSumRow(table, rows, numColumns);

                foreach (int key in rows.Keys)
                {
                    table.Rows.InsertAt(rows[key], key);
                }

                table.Rows.Add(sumRow);
                return table;
            }
            /// <summary>
            /// 向DataTable中添加 行分组汇总列
            /// </summary>
            /// <param name="olDtable">DataTable</param>
            /// <param name="bjName">分组列</param> 
            /// <returns></returns>
            public static DataTable AddGurop(DataTable olDtable, string bjName)
            {

                //为null 或 只有一条记录对于分组来说无意义
                if (olDtable == null)
                {
                    return olDtable;
                }
                DataTable table = TableSort(olDtable, bjName);
                Dictionary<int, DataRow> rows = new Dictionary<int, DataRow>();//存放汇总行
                IList<string> numColumns = GetNumColumns(table);
                string prevDept = table.Rows[0][bjName].ToString();//
                int NoOwn = 0;//同组项的第一行记录的位置
                int index = -1;//索引
                foreach (DataRow item in table.Rows)
                {
                    index++;//当前行索引 
                    //如果相邻两行 分组标记相同 则继续寻找下行，否则该行为同组的最后一行。进行数据处理
                    //item[bjName].ToString() == prevDept 表示为同行 则继续比较下一行
                    if (item[bjName].ToString() == prevDept && index != table.Rows.Count - 1)
                    {
                        continue;
                    }
                    else if (index == table.Rows.Count - 1)
                    {
                        if (item[bjName].ToString() != prevDept)
                        {
                            DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                            rows.Add(index + rows.Count, row);

                            DataRow row2 = table.NewRow();
                            foreach (string columnName in numColumns)
                            {
                                row2[columnName] = item[columnName];
                            }
                            rows.Add(index + rows.Count + 1, row2);
                        }
                        else
                        {
                            DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                            rows.Add(index + rows.Count + 1, row);
                        }

                    }
                    else
                    {
                        prevDept = item[bjName].ToString();//当前分组标记
                        DataRow row = CreateGroupRow(table, numColumns, NoOwn, index);
                        NoOwn = index;
                        rows.Add(index + rows.Count, row);
                    }
                }

                DataRow sumRow = CreateSumRow(table, rows, numColumns);

                foreach (int key in rows.Keys)
                {
                    table.Rows.InsertAt(rows[key], key);
                }

                table.Rows.Add(sumRow);
                return table;
            }

            /// <summary>
            /// 生成总计行
            /// </summary>
            /// <param name="table">DataTalbe</param>
            /// <param name="rows">汇总行集合</param>
            /// <param name="numColumns">累计列</param>
            /// <returns>总计行</returns>
            private static DataRow CreateSumRow(DataTable table, Dictionary<int, DataRow> rows, IList<string> numColumns)
            {
                DataRow sumRow = table.NewRow();
                sumRow[0] = "合计";
                foreach (string columnName in numColumns)
                {
                    foreach (int key in rows.Keys)
                    {
                        object count = sumRow[columnName];//汇总行 列值 
                        //如果值为null 或 "" 则默认为 0
                        if (count == null || count.ToString().Trim() == "")
                        {
                            count = 0;
                        }
                        sumRow[columnName] = decimal.Parse(count.ToString()) + decimal.Parse(rows[key][columnName].ToString());//累加
                    }

                }
                return sumRow;
            }

            private static IList<string> GetNumColumns(DataTable table)
            {
                IList<string> numColumns = new List<string>();//存放数字行
                foreach (DataColumn column in table.Columns)
                {
                    if (column.DataType == typeof(Decimal) || column.DataType == typeof(Int32)
                         || column.DataType == typeof(Int64) | column.DataType == typeof(float)
                         || column.DataType == typeof(Int64) | column.DataType == typeof(Double)
                        )
                    {
                        numColumns.Add(column.ColumnName);
                    }
                }
                return numColumns;
            }
            /// <summary>
            /// 将dataTable排序
            /// </summary>
            /// <param name="olDtable">DataTable</param>
            /// <param name="bjName">排序字段</param>
            /// <returns></returns>
            public static DataTable TableSort(DataTable olDtable, string bjName)
            {
                DataTable table = olDtable.Clone();
                DataRow[] sortRows = olDtable.Select(null, bjName);
                foreach (DataRow item in sortRows)
                {
                    table.ImportRow(item);
                }
                return table;
            }
            /// <summary>
            /// 生成汇总行
            /// </summary>
            /// <param name="table">分组表</param>
            /// <param name="numColumns">需要汇总的列</param>
            /// <param name="NoOwn">开始行</param>
            /// <param name="index">结束行</param>
            /// <returns>汇总行</returns>
            private static DataRow CreateGroupRow(DataTable table, IList<string> numColumns, int startRowIndex, int endRowIndex)
            {
                DataRow row = table.NewRow();//汇总行
                //从同组项的第一行记录的位置  到 同组的最后一行
                for (int i = startRowIndex; i < endRowIndex + 1; i++)
                {

                    foreach (string columnName in numColumns)
                    {

                        object count = row[columnName];//汇总行 列值 
                        object tempt = table.Rows[i][columnName];//当前行 列值
                        //如果值为null 或 "" 则默认为 0
                        if (count == null || count.ToString().Trim() == "")
                        {
                            count = 0;
                        }
                        if (tempt == null || tempt.ToString().Trim() == "")
                        {
                            tempt = 0;
                        }
                        row[columnName] = decimal.Parse(count.ToString()) + decimal.Parse(tempt.ToString());//累加
                    }
                }
                return row;
            }

            /// <summary>  
            /// 合并单元格 合并一行中的几列  
            /// </summary>  
            /// <param name="GridView1">GridView对象</param>  
            /// <param name="rows">行索引</param>  
            /// <param name="sCol">开始列</param>  
            /// <param name="eCol">结束列</param>  
            public static void GroupRow(GridView gridView, int rows, int sCol, int eCol)
            {
                TableCell oldTc = gridView.Rows[rows].Cells[sCol];
                for (int i = 1; i < eCol - sCol; i++)
                {
                    TableCell tc = gridView.Rows[rows].Cells[i + sCol]; 　 //Cells[0]就是你要合并的列  
                    tc.Visible = false;
                    if (oldTc.ColumnSpan == 0)
                    {
                        oldTc.ColumnSpan = 1;
                    }
                    oldTc.ColumnSpan++;
                    oldTc.VerticalAlign = VerticalAlign.Middle;
                }
            }
            /// <summary>
            /// 合并列
            /// </summary>
            /// <param name="gv">gridview对象</param>
            /// <param name="cells">列索引</param>
            /// <param name="sRow">合并列开始位置</param>
            /// <param name="eRow">合并列结束位置</param>
            public static void GropCell(GridView gv, int cells, int sRow, int eRow)
            {
                TableCell tc = gv.Rows[sRow].Cells[cells];
                tc.RowSpan = eRow - sRow + 1;
                for (int i = sRow + 1; i <= eRow; i++)
                {
                    gv.Rows[i].Cells[cells].Visible = false;
                }
            }
        }
        public void ToExcel(GridView _GV,string filename)
          {
              try
              {
                  HttpContext.Current.Response.Clear();
                  HttpContext.Current.Response.Buffer = true;
                  HttpContext.Current.Response.Charset = "utf-8";
                  HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + filename+".xls");
                  //如果设置为 GetEncoding("GB2312");导出的文件将会出现乱码！！！
                  HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
                  //设置输出文件类型为excel文件。
                  HttpContext.Current.Response.ContentType = "application/ms-excel";
                  //定义文件流，和控件输出流，建立关联。
                  System.IO.StringWriter oStringWriter = new System.IO.StringWriter();
                  System.Web.UI.Html32TextWriter oHtmlTextWriter = new Html32TextWriter(oStringWriter);
                  //将控件的信息写到输出流。
                  _GV.RenderControl(oHtmlTextWriter);
                  HttpContext.Current.Response.Output.Write(oStringWriter.ToString());
                  HttpContext.Current.Response.Flush();
                  HttpContext.Current.Response.End();
        
              }
              catch //(System.Exception ex)
              {
              	
              }
          }
        public void ToExcel(DataTable dt, string filename)
        {
            try
            {
                if (dt == null) return;
                List<string> columns =new List<string>();
                List<string> captions = new List<string>();
                foreach (DataColumn column in dt.Columns)
                {
                    columns.Add(column.ColumnName);
                    captions.Add(column.Caption??column.ColumnName);
                }
                JExcel.ExportExcel(dt, columns.ToArray(), captions.ToArray(), filename);

            }
            catch //(System.Exception ex)
            {

            }
        }
        /// <summary>
        /// 重写表头
        /// </summary>
        /// <param name="targetHeader">目标表头</param>
        /// <param name="newHeaderNames">新表头</param>
        /// <remarks>
        /// </remarks>
        public void SplitTableHeader(GridViewRow targetHeader, string newHeaderNames)
        {
            TableCellCollection tcl = targetHeader.Cells; //获得表头元素的实例
            tcl.Clear(); //清除元素
            int row = GetRowCount(newHeaderNames);
            int col = GetColCount(newHeaderNames);
            string[,] nameList = ConvertList(newHeaderNames, row, col);
            int RowSpan = 0;
            int ColSpan = 0;
            for (int k = 0; k < row; k++)
            {
                string LastFName = "";
                for (int i = 0; i < col; i++)
                {
                    if (LastFName == nameList[i, k] && k != row - 1)
                    {
                        LastFName = nameList[i, k];
                        continue;
                    }
                    else
                    {
                        LastFName = nameList[i, k];
                    }
                    int bFlag = IsVisible(nameList, k, i, LastFName);
                    switch (bFlag)
                    {
                        case 0:
                            break;
                        case 1:
                            RowSpan = GetSpanRowCount(nameList, row, k, i);
                            ColSpan = GetSpanColCount(nameList, row, col, k, i);
                            tcl.Add(new TableHeaderCell()); //添加表头控件
                            tcl[tcl.Count - 1].RowSpan = RowSpan;
                            tcl[tcl.Count - 1].ColumnSpan = ColSpan;
                            tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;
                            tcl[tcl.Count - 1].Text = LastFName;
                            break;
                        case -1:
                            string[] EndColName = LastFName.Split(new char[] { ',' });
                            foreach (string eName in EndColName)
                            {
                                tcl.Add(new TableHeaderCell()); //添加表头控件
                                tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;
                                tcl[tcl.Count - 1].Text = eName;
                            }
                            break;
                    }
                }
                if (k != row - 1)
                { //不是起始行,加入新行标签
                    tcl[tcl.Count - 1].Text = tcl[tcl.Count - 1].Text + "</th></tr><tr  class=\"" + targetHeader.CssClass + "\">";
                }
            }
        }
        /**/
        /// <summary>
        /// 重写表头
        /// </summary>
        /// <param name="targetHeader">目标表头</param>
        /// <param name="newHeaderNames">新表头</param>
        /// <remarks>
        /// </remarks>
        public void SplitTableHeader(DataGridItem targetHeader, string newHeaderNames)
        {
            TableCellCollection tcl = targetHeader.Cells; //获得表头元素的实例
            tcl.Clear(); //清除元素
            int row = GetRowCount(newHeaderNames);
            int col = GetColCount(newHeaderNames);
            string[,] nameList = ConvertList(newHeaderNames, row, col);
            int RowSpan = 0;
            int ColSpan = 0;
            for (int k = 0; k < row; k++)
            {
                string LastFName = "";
                for (int i = 0; i < col; i++)
                {
                    if (LastFName == nameList[i, k] && k != row - 1)
                    {
                        LastFName = nameList[i, k];
                        continue;
                    }
                    else
                    {
                        LastFName = nameList[i, k];
                    }
                    int bFlag = IsVisible(nameList, k, i, LastFName);
                    switch (bFlag)
                    {
                        case 0:
                            break;
                        case 1:
                            RowSpan = GetSpanRowCount(nameList, row, k, i);
                            ColSpan = GetSpanColCount(nameList, row, col, k, i);
                            tcl.Add(new TableHeaderCell()); //添加表头控件
                            tcl[tcl.Count - 1].RowSpan = RowSpan;
                            tcl[tcl.Count - 1].ColumnSpan = ColSpan;
                            tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;
                            tcl[tcl.Count - 1].Text = LastFName;
                            break;
                        case -1:
                            string[] EndColName = LastFName.Split(new char[] { ',' });
                            foreach (string eName in EndColName)
                            {
                                tcl.Add(new TableHeaderCell()); //添加表头控件
                                tcl[tcl.Count - 1].HorizontalAlign = HorizontalAlign.Center;
                                tcl[tcl.Count - 1].Text = eName;
                            }
                            break;
                    }
                }
                if (k != row - 1)
                { //不是起始行,加入新行标签
                    tcl[tcl.Count - 1].Text = tcl[tcl.Count - 1].Text + "</th></tr><tr class=\"" + targetHeader.CssClass + "\">";
                }
            }
        }
        /**/
        /// <summary>
        /// 如果上一行已经输出和当前内容相同的列头，则不显示
        /// </summary>
        /// <param name="ColumnList">表头集合</param>
        /// <param name="rowIndex">行索引</param>
        /// <param name="colIndex">列索引</param>
        /// <returns>1: 显示,-1:含','分隔符,0:不显示</returns>
        private int IsVisible(string[,] ColumnList, int rowIndex, int colIndex, string CurrName)
        {
            if (rowIndex != 0)
            {
                if (ColumnList[colIndex, rowIndex - 1] == CurrName)
                {
                    return 0;
                }
                else
                {
                    if (ColumnList[colIndex, rowIndex].Contains(","))
                    {
                        return -1;
                    }
                    else
                    {
                        return 1;
                    }
                }
            }
            return 1;
        }
        /**/
        /// <summary>
        /// 取得和当前索引行及列对应的下级的内容所跨的行数
        /// </summary>
        /// <param name="ColumnList"& gt;表头集合</param>
        /// <param name="row"& gt;行数</param>
        /// <param name="rowIndex"& gt;行索引</param>
        /// <param name="colIndex"& gt;列索引</param>
        /// <returns> 行数</returns>
        private int GetSpanRowCount(string[,] ColumnList, int row, int rowIndex, int colIndex)
        {
            string LastName = "";
            int RowSpan = 1;
            for (int k = rowIndex; k < row; k++)
            {
                if (ColumnList[colIndex, k] == LastName)
                {
                    RowSpan++;
                }
                else
                {
                    LastName = ColumnList[colIndex, k];
                }
            }
            return RowSpan;
        }
        /**/
        /// <summary>
        /// 取得和当前索引行及列对应的下级的内容所跨的列数
        /// </summary>
        /// <param name="ColumnList"& gt;表头集合</param>
        /// <param name="row"& gt;行数</param>
        /// <param name="col"& gt;列数</param>
        /// <param name="rowIndex"& gt;行索引</param>
        /// <param name="colIndex"& gt;列索引</param>
        /// <returns>列数< /returns>
        private int GetSpanColCount(string[,] ColumnList, int row, int col, int rowIndex, int colIndex)
        {
            string LastName = ColumnList[colIndex, rowIndex];
            int ColSpan = ColumnList[colIndex, row - 1].Split(new char[] { ',' }).Length;
            ColSpan = ColSpan == 1 ? 0 : ColSpan;
            for (int i = colIndex + 1; i < col; i++)
            {
                if (ColumnList[i, rowIndex] == LastName)
                {
                    ColSpan += ColumnList[i, row - 1].Split(new char[] { ',' }).Length;
                }
                else
                {
                    LastName = ColumnList[i, rowIndex];
                    break;
                }
            }
            return ColSpan;
        }
        /**/
        /// <summary>
        /// 将已定义的表头保存到数组
        /// </summary>
        /// <param name="newHeaders"& gt;新表头</param>
        /// <param name="row"& gt;行数</param>
        /// <param name="col"& gt;列数</param>
        /// <returns>表头数组</returns>
        private string[,] ConvertList(string newHeaders, int row, int col)
        {
            string[] ColumnNames = newHeaders.Split(new char[] { '#' });
            string[,] news = new string[col, row];
            string Name = "";
            for (int i = 0; i < col; i++)
            {
                string[] CurrColNames = ColumnNames[i].ToString().Split(new char[] { ' ' });
                for (int k = 0; k < row; k++)
                {
                    if (CurrColNames.Length - 1 >= k)
                    {
                        if (CurrColNames[k].Contains(","))
                        {
                            if (CurrColNames.Length != row)
                            {
                                if (Name == "")
                                {
                                    news[i, k] = news[i, k - 1];
                                    Name = CurrColNames[k].ToString();
                                }
                                else
                                {
                                    news[i, k + 1] = Name;
                                    Name = "";
                                }
                            }
                            else
                            {
                                news[i, k] = CurrColNames[k].ToString();
                            }
                        }
                        else
                        {
                            news[i, k] = CurrColNames[k].ToString();
                        }
                    }
                    else
                    {
                        if (Name == "")
                        {
                            news[i, k] = news[i, k - 1];
                        }
                        else
                        {
                            news[i, k] = Name;
                            Name = "";
                        }
                    }
                }
            }
            return news;
        }
        /**/
        /// <summary>
        /// 取得复合表头的行数
        /// </summary>
        /// <param name="newHeaders"& gt;新表头</param>
        /// <returns>行数< /returns>
        private int GetRowCount(string newHeaders)
        {
            string[] ColumnNames = newHeaders.Split(new char[] { '#' });
            int Count = 0;
            foreach (string name in ColumnNames)
            {
                int TempCount = name.Split(new char[] { ' ' }).Length;
                if (TempCount > Count)
                    Count = TempCount;
            }
            return Count;
        }
        /**/
        /// <summary>
        /// 取得复合表头的列数
        /// </summary>
        /// <param name="newHeaders"& gt;新表头</param>
        /// <returns>列数< /returns>
        private int GetColCount(string newHeaders)
        {
            return newHeaders.Split(new char[] { '#' }).Length;
        }

    }
}
